#include <stdio.h>

#include "boinc_api.h"
#include "diagnostics.h"     
#include "filesys.h"         
#include "str_util.h"            

// version.h is only used to get BOINC version numbers
#include "version.h"
 
const int N = 16; 
const int blocksize = 16; 
 
__global__ 
void hello(char *a, int *b) 
{
	a[threadIdx.x] += b[threadIdx.x];
}
 
int main()
{
	//initial for BOINC
	int rc;
	char resolved_name[512];
	FILE* f;

	//inital for CUDA
	char a[N] = "Hello \0\0\0\0\0\0";
	int b[N] = {15, 10, 6, 0, -11, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
	char *ad;
	int *bd;
	const int csize = N*sizeof(char);
	const int isize = N*sizeof(int);
	
	boinc_init_diagnostics(BOINC_DIAG_REDIRECTSTDERR|
                         BOINC_DIAG_MEMORYLEAKCHECKENABLED|
                         BOINC_DIAG_DUMPCALLSTACKENABLED|
                         BOINC_DIAG_TRACETOSTDERR);

  	/* Output written to stderr will be returned with the Result (task) */

  	fprintf(stderr,"Hello, stderr!\n");


  	/* BOINC apps that do not use graphics just call boinc_init() */

  	rc = boinc_init();
  	if (rc){
    		fprintf(stderr, "APP: boinc_init() failed. rc=%d\n", rc);
    		fflush(0);
    		exit(rc);
  	}

	rc = boinc_resolve_filename("out.txt", resolved_name, sizeof(resolved_name));
  	
	if (rc){
    		fprintf(stderr, "APP: cannot resolve output file name. RC=%d\n", rc);
    		boinc_finish(rc);    /* back to BOINC core */
  	}

	f = boinc_fopen(resolved_name, "a");

	fprintf(f,"%s", a);
 
	cudaMalloc( (void**)&ad, csize ); 
	cudaMalloc( (void**)&bd, isize ); 
	cudaMemcpy( ad, a, csize, cudaMemcpyHostToDevice ); 
	cudaMemcpy( bd, b, isize, cudaMemcpyHostToDevice ); 
	
	dim3 dimBlock( blocksize, 1 );
	dim3 dimGrid( 1, 1 );
	hello<<<dimGrid, dimBlock>>>(ad, bd);
	cudaMemcpy( a, ad, csize, cudaMemcpyDeviceToHost ); 
	cudaFree( ad );
	
	fprintf(f,"%s\n", a);

	{ int j, num, M;
		M = 123456789;
		fprintf(f, "Starting some computation...\n");
    		for ( j=0 ; j<M ; j++ ){
      			num=rand()+rand();     
    		}
    	fprintf(f, "Computation completed.\n");

	}

	fclose(f);
	fprintf(stderr,"bye!\n");
	
	//BOINC finish
	boinc_finish(0);
	//return EXIT_SUCCESS;
}
